import { BadRequestException, Body, Controller, Delete, Get, Logger, Post, Query, Req } from "@nestjs/common";
import { ApiBody, ApiConsumes, ApiOperation, ApiTags } from "@nestjs/swagger";
import { Public } from "../auth/decorators/public.decorator";
import { BooksService } from "./books.service";
import { BookCreateDto, BookDelDto, CatalogCreateDto, CatalogDelDto, CatalogUpdateDto } from "./books.dto";
import {FastifyRequest} from 'fastify'
import { plainToInstance } from "class-transformer";
import { validate } from "class-validator";
import { BusinessException } from "~/common/exceptions/biz.exception";

@ApiTags("Books - 书籍")
@Controller('books')
export class BooksController {
	private readonly logger = new Logger(BooksController.name);

	constructor(
		private readonly booksService: BooksService
	) { }

	@Post('add')
	@Public()
	@ApiOperation({summary: '添加书籍'})
  @ApiConsumes('multipart/form-data')
  @ApiBody({type: BookCreateDto})
	async createBook(@Req() req: FastifyRequest) {
		try {
      const params: Record<string, any> = req.body

      params.file = params.file[0]

      const accessUploadDto = plainToInstance(BookCreateDto, req.body)
      const errors = await validate(accessUploadDto)

      if (errors.length) {
        // 取出 errors[0].constraints 中的第一个错误信息，constraints为一个对象结构
        const message = Object.values(errors[0].constraints)[0]
        throw new BadRequestException(message)
      }

      // 业务逻辑
			return await this.booksService.createBook(accessUploadDto)
    }
    catch (error) {
      throw new BadRequestException(error?.message ?? '上传失败')
    }
	}

	// 查询书籍列表、查询书籍、查询书籍下的目录、查询目录下某章节的内容
	@Get('/list')
	@ApiOperation({summary: '查询书籍列表'})
	async getBooks() {
		// 业务逻辑
		try {
			// 查询书籍列表
			return await this.booksService.getBooks()
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '查询书籍列表失败')
		}
	}

	@Delete('/del')
	@ApiOperation({summary: '删除书籍'})
	@ApiBody({type: BookDelDto})
	async delBook(@Body() book: BookDelDto) {
		// 业务逻辑
		try {
			// 删除书籍
			return await this.booksService.delBook(book.id)
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '删除书籍失败')
		}
	}

	@Post('/catalog/add')
	@Public()
	@ApiOperation({summary: '添加目录'})
	@ApiBody({type: CatalogCreateDto})
	async createCatalog(@Body() catalog: CatalogCreateDto) {
		// 业务逻辑
		try {
			// 更新字典
			return await this.booksService.createCatalog(catalog)
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '添加目录失败')
		}
	}

	@Post('/catalog/update')
	@ApiOperation({summary: '更新目录'})
	@ApiBody({type: CatalogUpdateDto})
	async updateCatalog(@Body() catalog: CatalogUpdateDto) {
		// 业务逻辑
		try {
			// 更新字典
			return await this.booksService.updateCatalog(catalog)
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '更新目录失败')
		}
	}

	@Get('/catalog/list')
	@ApiOperation({summary: '查询书籍的章节列表'})
	async getCatalogByBook(@Query('id') bookId: number) {
		// 业务逻辑
		try {
			// 查询书籍列表
			return await this.booksService.getCatalogByBookId(bookId)
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '查询书籍章节列表失败')
		}
	}

	@Get('/catalog/content')
	@ApiOperation({summary: '查询书籍的章节内容'})
	async getCatalogContent(@Query('id') catalogId: number) {
		// 业务逻辑
		try {
			// 查询书籍列表
			return await this.booksService.getCatalogContent(catalogId)
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '查询书籍章节内容失败')
		}
	}

	@Delete('/catalog/del')
	@ApiOperation({summary: '删除目录'})
	@ApiBody({type: CatalogDelDto})
	async delCatalog(@Body() catalog: CatalogDelDto) {
		// 业务逻辑
		try {
			// 删除目录
			return await this.booksService.delCatalog(catalog.id)
		}
		catch (error: any) {
			throw new BusinessException(error?.message ?? '删除目录失败')
		}
	}
}